package com.adee.design.action.chain;

import lombok.Data;

/*
* 责任链模式
*
* */
public class Test {
    public static void main(String[] args) {
        FilterChain.Builder builder = new FilterChain().new Builder();
        FilterChain filterChain = builder.setNextFilter(new AbstractFilter() {
            @Override
            protected boolean doProcess() {
                System.out.println("编码处理");
                return true;
            }
        }).setNextFilter(new AbstractFilter() {
            @Override
            protected boolean doProcess() {
                System.out.println("协议封装");
                return true;
            }
        }).build();
        filterChain.process();
    }

    // 过滤器接口
    @FunctionalInterface
    interface Filter {
        void process();
        default Filter setNext(Filter next) {return null;}
    }

    // 具体过滤器
    static abstract class AbstractFilter implements Filter{
        private Filter next;

        @Override
        public void process() {
            doFilter(doProcess());
        }

        // 返回true继续执行后面filter，false停止执行后面filter
        abstract protected boolean doProcess();

        private void doFilter(boolean doNext) {
            if(doNext && null != next) {
                next.process();
            }
        }

        public Filter setNext(Filter next) {
            this.next = next;
            return next;
        }

        public Filter getNext() {
            return next;
        }
    }

    // 过滤器链
    @Data
    static class FilterChain {
        private Filter head;
        private Filter tail;
        class Builder {
            Builder setNextFilter(Filter f) {
                if(null == head) {
                    FilterChain.this.head = f;
                } else {
                    FilterChain.this.tail.setNext(f);
                }
                FilterChain.this.tail = f;
                return this;
            }
            FilterChain build() {
                return FilterChain.this;
            }
        }

        public void process() {
            if(null != head)
                head.process();
        }
    }
}
